using Microsoft.Extensions.Logging;
using SumerCoreDevOps.Domain.Entities;
using SumerCoreDevOps.Infrastructure.Data;

namespace SumerCoreDevOps.Infrastructure.Identity;

/// <summary>
/// 用户管理器
/// </summary>
public class UserManager
{
    private readonly FreeSQLProvider _dbProvider;
    private readonly ILogger<UserManager> _logger;

    public UserManager(FreeSQLProvider dbProvider, ILogger<UserManager> logger)
    {
        _dbProvider = dbProvider;
        _logger = logger;
    }

    /// <summary>
    /// 创建用户
    /// </summary>
    public async Task<User> CreateUserAsync(
        string username,
        string email,
        string password,
        string? displayName = null,
        string? phoneNumber = null,
        string? createdBy = null)
    {
        // 检查用户名是否已存在
        var existingUser = await _dbProvider.Orm.Select<User>()
            .Where(u => u.Username == username || u.Email == email)
            .FirstAsync();

        if (existingUser != null)
        {
            throw new InvalidOperationException("用户名或邮箱已存在");
        }

        // 生成密码哈希
        var (passwordHash, passwordSalt) = HashPassword(password);

        var user = new User
        {
            Username = username,
            Email = email,
            DisplayName = displayName ?? username,
            PhoneNumber = phoneNumber,
            PasswordHash = passwordHash,
            PasswordSalt = passwordSalt,
            IsEnabled = true,
            CreatedAt = DateTime.UtcNow,
            CreatedBy = createdBy,
            MustChangePassword = true // 首次登录需要修改密码
        };

        await _dbProvider.Orm.Insert(user).ExecuteAffrowsAsync();
        _logger.LogInformation("创建用户成功: {Username}", username);

        return user;
    }

    /// <summary>
    /// 验证用户登录
    /// </summary>
    public async Task<User?> ValidateCredentialsAsync(string username, string password, string? ipAddress = null)
    {
        var user = await _dbProvider.Orm.Select<User>()
            .Where(u => u.Username == username || u.Email == username)
            .FirstAsync();

        if (user == null)
        {
            _logger.LogWarning("用户不存在: {Username}", username);
            return null;
        }

        // 检查是否锁定
        if (user.IsLocked)
        {
            _logger.LogWarning("用户已锁定: {Username}", username);
            return null;
        }

        // 检查是否启用
        if (!user.IsEnabled)
        {
            _logger.LogWarning("用户未启用: {Username}", username);
            return null;
        }

        // 验证密码
        if (!VerifyPassword(password, user.PasswordHash, user.PasswordSalt))
        {
            // 增加失败次数
            user.FailedLoginAttempts++;
            if (user.FailedLoginAttempts >= 5)
            {
                user.IsLocked = true;
                user.LockReason = "连续登录失败次数过多";
                user.LockedAt = DateTime.UtcNow;
                _logger.LogWarning("用户因登录失败次数过多被锁定: {Username}", username);
            }

            await _dbProvider.Orm.Update<User>()
                .SetSource(user)
                .ExecuteAffrowsAsync();

            return null;
        }

        // 登录成功，重置失败次数并更新最后登录信息
        user.FailedLoginAttempts = 0;
        user.LastLoginAt = DateTime.UtcNow;
        user.LastLoginIp = ipAddress;

        await _dbProvider.Orm.Update<User>()
            .SetSource(user)
            .ExecuteAffrowsAsync();

        _logger.LogInformation("用户登录成功: {Username}", username);
        return user;
    }

    /// <summary>
    /// 获取用户（包含角色）
    /// </summary>
    public async Task<User?> GetUserWithRolesAsync(long userId)
    {
        var user = await _dbProvider.Orm.Select<User>()
            .Where(u => u.Id == userId)
            .FirstAsync();

        if (user == null)
        {
            return null;
        }

        // 手动加载角色关联
        var roles = await _dbProvider.Orm.Select<Role>()
            .InnerJoin<UserRole>((r, ur) => r.Id == ur.RoleId)
            .Where<UserRole>(ur => ur.UserId == userId)
            .ToListAsync();

        user.Roles = roles;
        return user;
    }

    /// <summary>
    /// 获取用户的所有权限
    /// </summary>
    public async Task<List<Permission>> GetUserPermissionsAsync(long userId)
    {
        // 使用子查询方式获取用户的所有权限
        return await _dbProvider.Orm.Select<Permission>()
            .Where(p => _dbProvider.Orm.Select<RolePermission>()
                .InnerJoin<UserRole>((rp, ur) => rp.RoleId == ur.RoleId)
                .Where(rp => rp.PermissionId == p.Id)
                .Where<UserRole>(ur => ur.UserId == userId)
                .Any())
            .Where(p => p.IsSystem == false)
            .Distinct()
            .ToListAsync();
    }

    /// <summary>
    /// 修改密码
    /// </summary>
    public async Task ChangePasswordAsync(long userId, string oldPassword, string newPassword)
    {
        var user = await _dbProvider.Orm.Select<User>()
            .Where(u => u.Id == userId)
            .FirstAsync();

        if (user == null)
        {
            throw new InvalidOperationException("用户不存在");
        }

        // 验证旧密码
        if (!VerifyPassword(oldPassword, user.PasswordHash, user.PasswordSalt))
        {
            throw new InvalidOperationException("旧密码不正确");
        }

        // 生成新密码哈希
        var (passwordHash, passwordSalt) = HashPassword(newPassword);
        user.PasswordHash = passwordHash;
        user.PasswordSalt = passwordSalt;
        user.MustChangePassword = false;
        user.PasswordExpiresAt = DateTime.UtcNow.AddDays(90); // 90天后过期
        user.UpdatedAt = DateTime.UtcNow;

        await _dbProvider.Orm.Update<User>()
            .SetSource(user)
            .ExecuteAffrowsAsync();

        _logger.LogInformation("用户修改密码成功: {UserId}", userId);
    }

    /// <summary>
    /// 重置密码（管理员操作）
    /// </summary>
    public async Task<string> ResetPasswordAsync(long userId, string? adminUser = null)
    {
        var user = await _dbProvider.Orm.Select<User>()
            .Where(u => u.Id == userId)
            .FirstAsync();

        if (user == null)
        {
            throw new InvalidOperationException("用户不存在");
        }

        // 生成随机密码
        var newPassword = GenerateRandomPassword();
        var (passwordHash, passwordSalt) = HashPassword(newPassword);

        user.PasswordHash = passwordHash;
        user.PasswordSalt = passwordSalt;
        user.MustChangePassword = true;
        user.UpdatedAt = DateTime.UtcNow;
        user.UpdatedBy = adminUser;

        await _dbProvider.Orm.Update<User>()
            .SetSource(user)
            .ExecuteAffrowsAsync();

        _logger.LogInformation("管理员重置用户密码: UserId={UserId}, Admin={Admin}", userId, adminUser);
        return newPassword;
    }

    /// <summary>
    /// 锁定用户
    /// </summary>
    public async Task LockUserAsync(long userId, string reason, string? lockedBy = null)
    {
        await _dbProvider.Orm.Update<User>()
            .Set(u => u.IsLocked, true)
            .Set(u => u.LockReason, reason)
            .Set(u => u.LockedAt, DateTime.UtcNow)
            .Set(u => u.UpdatedAt, DateTime.UtcNow)
            .Set(u => u.UpdatedBy, lockedBy)
            .Where(u => u.Id == userId)
            .ExecuteAffrowsAsync();

        _logger.LogInformation("锁定用户: UserId={UserId}, Reason={Reason}", userId, reason);
    }

    /// <summary>
    /// 解锁用户
    /// </summary>
    public async Task UnlockUserAsync(long userId, string? unlockedBy = null)
    {
        await _dbProvider.Orm.Update<User>()
            .Set(u => u.IsLocked, false)
            .Set(u => u.LockReason, null)
            .Set(u => u.LockedAt, null)
            .Set(u => u.FailedLoginAttempts, 0)
            .Set(u => u.UpdatedAt, DateTime.UtcNow)
            .Set(u => u.UpdatedBy, unlockedBy)
            .Where(u => u.Id == userId)
            .ExecuteAffrowsAsync();

        _logger.LogInformation("解锁用户: UserId={UserId}", userId);
    }

    /// <summary>
    /// 获取所有用户
    /// </summary>
    public async Task<List<User>> GetAllUsersAsync()
    {
        return await _dbProvider.Orm.Select<User>()
            .OrderByDescending(u => u.CreatedAt)
            .ToListAsync();
    }

    /// <summary>
    /// 哈希密码（使用 BCrypt）
    /// </summary>
    private (string hash, string salt) HashPassword(string password)
    {
        // 生成 BCrypt 盐
        var salt = BCrypt.Net.BCrypt.GenerateSalt();

        // 使用 BCrypt 哈希密码
        var hash = BCrypt.Net.BCrypt.HashPassword(password, salt);

        return (hash, salt);
    }

    /// <summary>
    /// 验证密码（使用 BCrypt）
    /// </summary>
    private bool VerifyPassword(string password, string storedHash, string? storedSalt)
    {
        if (string.IsNullOrEmpty(storedHash))
        {
            return false;
        }

        // BCrypt.Verify 会自动处理盐值（盐已包含在哈希中）
        // 所以不需要单独的 storedSalt 参数
        return BCrypt.Net.BCrypt.Verify(password, storedHash);
    }

    /// <summary>
    /// 生成随机密码
    /// </summary>
    private string GenerateRandomPassword(int length = 12)
    {
        const string chars = "ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnpqrstuvwxyz23456789!@#$%";
        var random = new Random();
        return new string(Enumerable.Repeat(chars, length)
            .Select(s => s[random.Next(s.Length)]).ToArray());
    }
}
